package com.project.card;

import static com.project.card.util.UrlUtil.SERVER_URL;

import android.Manifest;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.lifecycle.LifecycleOwner;


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.card.bean.UserBean;
import com.project.card.util.BitmapUtil;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;

import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class InfoActivity extends AppCompatActivity {

    private ImageView infoImg;
    private Button btnSelect;
    private Button btnRecognize;
    private Button btnConfirm;

    private EditText editName;
    private EditText editEthnic;
    private EditText editBirth;
    private EditText editAddr;
    private EditText editCode;
    private EditText editComment;
    private EditText editPhone;
    private EditText editPassword;
    
    private SharedPreferences sp;


    private static final int REQUEST_CAMERA_PERMISSION = 100;
    private ActivityResultLauncher launcherCamera;
    private ActivityResultLauncher<Intent> selectImageLauncher;
    private Uri imageUri;
    private String string64;
    private JsonNode jsonNode;

    private final int CAMERA_REQUEST = 10;

    private String[] permissions=new String[]{
            Manifest.permission.CAMERA,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    public static final ObjectMapper JSONMAPPER = new ObjectMapper()
            .enable(JsonParser.Feature.IGNORE_UNDEFINED)
            .enable(JsonParser.Feature.ALLOW_COMMENTS)
            .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
            .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
            .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_info);

        infoImg = findViewById(R.id.info_img);
        btnSelect = findViewById(R.id.info_select);
        btnRecognize = findViewById(R.id.info_recognize);
        btnConfirm = findViewById(R.id.info_confirm);

        editName = findViewById(R.id.info_edit_name);
        editEthnic = findViewById(R.id.info_edit_ethnic);
        editBirth = findViewById(R.id.info_edit_birth);
        editAddr = findViewById(R.id.info_edit_addr);
        editCode = findViewById(R.id.info_edit_code);
        editComment = findViewById(R.id.info_edit_comment);
        editPhone = findViewById(R.id.info_edit_phone);
        editPassword = findViewById(R.id.info_edit_password);

        launcherCamera = registerForActivityResult(
                new ActivityResultContracts.TakePicture(), result -> {
                    if(result){
                        Bitmap bitmap = BitmapUtil.getAutoZoomImage(this, imageUri);
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        bitmap.compress(Bitmap.CompressFormat.JPEG,80,baos);
                        byte[] bdata = baos.toByteArray();
                        string64 = Base64.encodeToString(bdata, Base64.DEFAULT);
                        infoImg.setImageBitmap(bitmap);
                    }
                }
        );

        infoImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(checkCameraPermission()){
                    takeOriginalPhoto();
                }else {
                    requestCameraPermission();
                }
            }
        });
        OkHttpClient client = new OkHttpClient();


        selectImageLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    if(result.getResultCode() == Activity.RESULT_OK && result.getData()!=null){
                        Uri imageUri = result.getData().getData();
                        infoImg.setImageURI(imageUri);
//                        try {
//                            Drawable drawable = infoImg.getDrawable();
//                            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
//                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//                            bitmap.compress(Bitmap.CompressFormat.JPEG,80,baos);
//                            byte[] bdata = baos.toByteArray();
//                            string64 = Base64.encodeToString(bdata, Base64.DEFAULT);
//                        }catch (Exception e){
//                            Log.e("bm",e.getMessage());
//                            e.printStackTrace();
//                        }
                    }
                });

        btnSelect.setOnClickListener(v -> {
            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            selectImageLauncher.launch(intent);
        });
        btnRecognize.setOnClickListener(v->{
            Drawable drawable = infoImg.getDrawable();
            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG,80,baos);
            byte[] bdata = baos.toByteArray();
            string64 = Base64.encodeToString(bdata, Base64.DEFAULT);

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try{
                        Request request = new Request.Builder()
                                .url("http://192.168.1.9:8080/user/recg")
                                .post(RequestBody.create(MediaType.parse("application/json"),string64))
                                .build();
                        Response response = client.newCall(request).execute();
                        String responseData = response.body().string();
                        jsonNode = JSONMAPPER.readTree(responseData);
                        String name = jsonNode.get("data").get("data").get("face").get("data").get("name").asText();
                        String ethnicity = jsonNode.get("data").get("data").get("face").get("data").get("ethnicity").asText();
                        String birthDay = jsonNode.get("data").get("data").get("face").get("data").get("birthDate").asText();
//                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年M月dd日");
//                        Date birthDate = simpleDateFormat.parse(birthDay);
                        String address = jsonNode.get("data").get("data").get("face").get("data").get("address").asText();
                        String idNumber = jsonNode.get("data").get("data").get("face").get("data").get("idNumber").asText();
                        
                        editName.setText(name);
                        editEthnic.setText(ethnicity);
                        editBirth.setText(birthDay);
                        editAddr.setText(address);
                        editCode.setText(idNumber);
                        
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        });


        btnConfirm.setOnClickListener(v ->{
            try {
                if(checkIdCardNum(editCode.getText().toString())){
                    UserBean user = new UserBean();
                    user.setPhone(editPhone.getText().toString());
                    user.setPassword(editPassword.getText().toString());
                    user.setCommentCode(genCommentCode());
                    user.setBalance(0);
                    user.setSchedule(0);
                    user.setCode(editCode.getText().toString());

                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try{
                                FormBody.Builder params = new FormBody.Builder();
                                params.add("phone",editPhone.getText().toString());
                                params.add("password",editPassword.getText().toString());
                                params.add("commentCode",genCommentCode());
                                params.add("code",editCode.getText().toString());
                                params.add("bonus",editComment.getText().toString());
                                Request request = new Request.Builder()
                                        .url(SERVER_URL+"user/regg")
                                        .post(params.build())
                                        .build();
                                Response response = client.newCall(request).execute();
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();

                    sp = getSharedPreferences("current_user",MODE_PRIVATE);
                    SharedPreferences.Editor editor  = sp.edit();
                    if(sp.getBoolean("login",false)){
                        editor.clear();
                        editor.commit();
                    }
                    editor.putBoolean("login",true);
                    editor.putString("name",editPhone.getText().toString());
                    editor.putString("code",editCode.getText().toString());
                    editor.putString("phone", editPhone.getText().toString());
                    editor.commit();
                    finish();
                }else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(InfoActivity.this, "请检查身份证号",Toast.LENGTH_LONG).show();
                        }
                    });
                }
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        });




    }

    public static String genCommentCode(){
        int  maxNum = 36;
        int i;
        int count = 0;
        char[] str = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
                'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
                'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
        StringBuffer gen = new StringBuffer("");
        Random r = new Random();
        while(count < 8){
            i = Math.abs(r.nextInt(maxNum));
            if (i >= 0 && i < str.length) {
                gen.append(str[i]);
                count ++;
            }
        }
        return gen.toString();
    }

    private boolean checkCameraPermission() {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void requestCameraPermission() {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
            // 显示权限说明对话框
            // 可以使用一个对话框或其他方式向用户解释为什么需要相机权限，并在用户同意后请求权限
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA_PERMISSION);
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                takeOriginalPhoto();
            } else {
                // 相机权限被拒绝，可以显示一条消息或执行其他操作
            }
        }
    }
    private void takeOriginalPhoto() {
        // Android10开始必须由系统自动分配路径，同时该方式也能自动刷新相册
        ContentValues values = new ContentValues();
        // 指定图片文件的名称
        values.put(MediaStore.Images.Media.DISPLAY_NAME, "photo_"+new Random().nextInt(8));
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");// 类型为图像
        // 通过内容解析器插入一条外部内容的路径信息
        imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        launcherCamera.launch(imageUri);
    }

    public boolean checkIdCardNum(String idNum) throws ParseException
    {
        idNum=idNum.toUpperCase(); //将末尾可能存在的x转成X

        String regex="";
        regex+="^[1-6]\\d{5}"; //前6位地址码。后面仍需打表校验

        regex+="(18|19|20)\\d{2}"; //年份。后面仍需校验
        regex+="((0[1-9])|(1[0-2]))"; //月份。后面仍需校验
        regex+="(([0-2][1-9])|10|20|30|31)"; //日期。后面仍需校验

        regex+="\\d{3}"; //3位顺序码

        regex+="[0-9X]"; //检验码。后面仍需验证

        if(!idNum.matches(regex))
            return false;

        //第1，2位(省)打表进一步校验
        int[] d={11,12,13,14,15,
                21,22,23,31,32,33,34,35,36,37,
                41,42,43,
                44,45,46,
                50,51,52,53,53,
                61,62,63,64,65,
                83,81,82};
        boolean flag=false;
        int prov=Integer.parseInt(idNum.substring(0, 2));
        for(int i=0;i<d.length;i++)
            if(d[i]==prov)
            {
                flag=true;
                break;
            }
        if(!flag)
            return false;

        //生日校验：生日的时间不能比当前时间（指程序检测用户输入的身份证号码的时候）晚
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
        Date birthDate=sdf.parse(idNum.substring(6, 14));
        Date curDate=new Date();
        if(birthDate.getTime()>curDate.getTime())
            return false;

        //生日校验：每个月的天数不一样（有的月份没有31），还要注意闰年的二月
        int year=Integer.parseInt(idNum.substring(6, 10));
        int leap=((year%4==0 && year%100!=0) || year%400==0)?1:0;
        final int[] month={0,31,28+leap,31,30,31,30,31,31,30,31,30,31};
        int mon=Integer.parseInt(idNum.substring(10, 12));
        int day=Integer.parseInt(idNum.substring(12, 14));
        if(day>month[mon])
        {
            //System.out.println(day+" "+month[mon]+"\n");
            //System.out.println("---");
            return false;
        }


        //检验码
        if(idNum.charAt(17)!=getLastChar(idNum))
            return false;

        return true;
    }

    //根据身份证号码的前17位计算校验码
    public char getLastChar(String idNum) //由于这个功能比较独立，就分离出来
    {
        final int[] w={0,7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
        final char[] ch={'1','0','X','9','8','7','6','5','4','3','2'}; //这就是为什么一开始将末尾可能存在的x转成X的原因
        int res=0;
        for(int i=0;i<17;i++)
        {
            int t=idNum.charAt(i)-'0';
            res+=(t*w[i+1]);
        }
        return ch[res%11];
    }
    

}